import { useState, useCallback, useEffect, useRef, Component, ReactNode, ReactPropTypes, useLayoutEffect } from 'react';
import { BlockitClient, BlockType, BlockSnapshot, DocumentRef, ExtendedSelectionItem, TextRef, TextSnapshot, TextType,UserInfo, BlockType, BlockId,ViewportChangeEvent } from '@lark-opdev/block-docs-addon-api';
import request, {post, get, sendStreamRequest} from './request';
import { APP_KEY, APP_ID, BASE_URL, LOGIN_PATH,XZ_APP_ID, CHAT_PATH } from './constant';
import './index.css';

import Markdown from 'react-markdown';


// 初始化BlockitClient
const DocMiniApp = new BlockitClient().initAPI();
// 判断是否为文本块
const isTextualBlock = (block: BlockSnapshot) => {
  return (
    block.type === BlockType.TEXT ||
    block.type.includes('heading') ||
    block.type === BlockType.BULLET ||
    block.type === BlockType.ORDERED ||
    block.type === BlockType.QUOTE ||
    block.type === BlockType.TODO
  );
};
// 获取文档字数
const getDocumentWordCount = async (docRef: DocumentRef) => {
  const blockSnapshot = await DocMiniApp.Document.getRootBlock(docRef);
  let number = 0;
  const getBlockWordCount = async (blockSnapshot: BlockSnapshot): Promise<void> => {
    if (isTextualBlock(blockSnapshot)) {
      number = number + blockSnapshot.data?.plain_text?.length;
    }
    for (const blockChildSnapshot of blockSnapshot.childSnapshots) {
      await getBlockWordCount(blockChildSnapshot);
    }
  };
  await getBlockWordCount(blockSnapshot);
  return number;
};

export default function App() {
  const [count, setCount] = useState<number>(0);
  const [tone, setTone] = useState<string>('');
  const [processing, setProcessing] = useState<string>('');
  const [documentTitle, setDocumentTitle] = useState<string>('');
  const [content, setContent] = useState<string>('');
  const [others, setOthers] = useState<string>('');
  const [resultContent, setResultContent] = useState<string>('');
  const [errorMsg, setErrorMsg] = useState<string>('');
  const [userInfo, setUserInfo] = useState<UserInfo|null>(null);
  const [mdmUserInfo, setMdmUserInfo] = useState<Object|null>(null);
  const [convId, setConvId] = useState<string>('');
  const [code, setCode] = useState<string>('');
  const [resultAreaHeight, setResultAreaHeight] = useState<number>(0);
  const interval = useRef<number>(new Date().getTime());
  const docRef = useRef<DocumentRef | null>(null);
  const [selectedBlock, setSelectedBlock] = useState<ExtendedSelectionItem | null>(null);
  const computeCount = useCallback(async (docRef: DocumentRef) => {
    let number = await getDocumentWordCount(docRef);
    setCount(number);
  }, []);
  const INTERVAL = 16;
  const selectionChangeCb = (selectedBlocks: BlockSnapshot[]) => {
    //一些操作
  }
  const viewportChangeHandler = async (event: ViewportChangeEvent) => {
    console.log(event);
    const rect = await DocMiniApp.Bridge.getContainerRect();
    console.log(rect);
    // if(rect.height - 350 > 180){
      setResultAreaHeight(rect.height - 350)
};
  useLayoutEffect(() => {
    login();
    (async () => {
      
    })();
  }, [])
  useEffect(() => {
    (async () => {
      //获取文档引用
      docRef.current = await DocMiniApp.getActiveDocumentRef();
      const docTitle = await DocMiniApp.Document.getTitle(docRef.current)
      setDocumentTitle(docTitle)
      //监听文档变化
      DocMiniApp.Selection.onSelectionChange(docRef.current, async (selectedBlocks: BlockSnapshot[]) => {
        let dnumber = 0
        let now = new Date().getTime();
        if (now - interval.current > INTERVAL) {
          computeCount(docRef.current as DocumentRef);
          interval.current = now;
        }

        const selection = await DocMiniApp.Selection.getSelection(docRef.current as DocumentRef);
        console.log(selection);
        
        setSelectedBlock(selection.slice(-1)[0]);
        
      });
      // DocMiniApp.Selection.onSelectionChange(docRef.current, selectionChangeCb);

      //初始化
      computeCount(docRef.current);
      DocMiniApp.Viewport.onViewportChange(viewportChangeHandler);
      
    })();
   
    // return () => {
    //   DocMiniApp.Selection.offSelectionChange(docRef.current, selectionChangeCb);    
    // };
    // return () => {
    //   (async () => {
    //     DocMiniApp.Selection.offSelectionChange(docRef.current, () => { });
    //   })();
    // };
  }, []);

  const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
    // 处理按钮事件
  };
  const handleProcessingClick = (e: React.MouseEvent<HTMLInputElement>) => {
    let value = (e.target as HTMLInputElement).value
    if(value === processing){
      setProcessing('')
    }else{
      setProcessing(value)
    }
  }

  const handleProcessingChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    // setProcessing(e.target.value)
  }

  const handleToneClick = (e: React.MouseEvent<HTMLInputElement>) => {
    let value = (e.target as HTMLInputElement).value
    if(value === tone){
      setTone('')
    }else{
      setTone(value)
    }
  }

  const handleToneChange = (e: React.ChangeEvent<HTMLInputElement>) => {
      setTone(e.target.value)
  }
  const handleOthersChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
    setOthers(e.target.value)
  }
  const login = async () => {
    const userInfo = await DocMiniApp.Service.User.getUserInfo()
    const code = await DocMiniApp.Service.User.login();
   
    setCode(code)
    setUserInfo(userInfo)

    let loginParams = {
      logonWay: 5,
      appId: APP_ID,
      code: code,
    };
    post(`${BASE_URL}${LOGIN_PATH}`,loginParams).then( async res => {
      if(res.ok){
        setMdmUserInfo(res.data)
      }
      const rect = await DocMiniApp.Bridge.getContainerRect();
      console.log(rect);
      // if(rect.height - 350 > 180){
        setResultAreaHeight(rect.height - 350)
      // }else{
      //   setResultAreaHeight(180)
      // }
    }
    ).catch(err => {
      setErrorMsg(err && err.message)
    })
   
  }
  

  const getBlockWords = async (block: BlockSnapshot| null) => {
    let blockSnapshot = block
      if (!blockSnapshot) {
        blockSnapshot = await DocMiniApp.Document.getRootBlock(docRef.current as DocumentRef);
      }
    let word = ''
    const getBlockWords =  async (blockSnapshot: BlockSnapshot): Promise<void> => {          
      if (isTextualBlock(blockSnapshot)) {
        word += blockSnapshot.data?.plain_text

        // const block = await DocMiniApp.Block.getBlock(blockSnapshot);
        // const rawText =  DocMiniApp.Block.TextBlock.getRawText(block.data as TextBlockData);  
        //  word +=  rawText

        // const DocMiniApp = new BlockitClient().initAPI();
        // const docRef = await DocMiniApp.getActiveDocumentRef();
        // const blockRef = DocMiniApp.getBlockRefById(docRef,3);
        // const block = await DocMiniApp.Block.getBlock(blockRef);
        // const rawText =  DocMiniApp.Block.TextBlock.getRawText(block.data as TextBlockData);
        // console.log(rawText);
        
      }
      for (const blockChildSnapshot of blockSnapshot.childSnapshots) {
        await getBlockWords(blockChildSnapshot);
      }
    }
    await getBlockWords(blockSnapshot);
    return word;
  };

  const appendBlockWithResultContent = async (e: React.MouseEvent<HTMLAnchorElement>) => {
    e.stopPropagation()
    e.preventDefault()
    if(!resultContent.trim())return;
    const blockSnap = await DocMiniApp.Document.getRootBlock(docRef.current as DocumentRef);
    if (selectedBlock) {
    
      const text = await DocMiniApp.Block.insertBlock(selectedBlock?.ref, selectedBlock.blockId, {
        type: BlockType.TEXT,
            data: {
              text: {
                elements: [
                  {
                    text_run: {
                      content:resultContent,
                      style: {
                          bold: true
                      }
                    }
                  }
                ]
              },
              plain_text: resultContent
            }
     });
    }else {
      const text = await DocMiniApp.Block.appendBlock(blockSnap.ref, {
        type: BlockType.TEXT,
        data: {
          text: {
            elements: [{
              text_run: {
                content:resultContent,
                style: {
                  bold: true
                }
              }
            }]
          },
          plain_text: resultContent
        }
      });
    }
  }
  const clean = async (e: React.MouseEvent<HTMLAnchorElement>) => {
    e.stopPropagation()
    e.preventDefault()
    setErrorMsg('')
    setResultContent('')
    setProcessing('')
    setTone('')
    setOthers('')
    setConvId('')
  }

  const confirm = async (rebuild: boolean = false) => {
    let convIdHere = convId
    if(!rebuild){
      setConvId('')
      convIdHere = ''
    }
    if(!mdmUserInfo?.token){
      setErrorMsg("未检测到您的用户信息，请您重新加载组件。")
      return
    }
    if(!processing && !tone){
      return
    }
    // 全部选中
    // const DocMiniApp = new BlockitClient().initAPI();
    // const docRef = await DocMiniApp.getActiveDocumentRef();
    // const block = await DocMiniApp.Document.getRootBlock(docRef);
    // await DocMiniApp.Selection.setSelection([{ type: 'block', ref: block.ref }]);

    // 获取选中
    const DocMiniApp = new BlockitClient().initAPI();
    const docRef = await DocMiniApp.getActiveDocumentRef();
    const selections = await DocMiniApp.Selection.getSelection(docRef) as [ExtendedSelectionItem];
    let selected_content = ""
    selections.forEach(selection => {
      let select_range = (selection.ref as TextRef).range
      if(!selection.blockSnapshot.data.plain_text){
        console.log(selection.blockSnapshot.data.plain_text);
        
      }
      selected_content +=selection.blockSnapshot.data.plain_text && selection.blockSnapshot.data.plain_text.slice(select_range[0], select_range[1]) + "\r\n" 
    });
   
    if(selected_content.trim().length === 0){
      selected_content = await getBlockWords(null)
    }
    // if(selected_content.length > 8192){
    //   setErrorMsg("需要解析的内容长度不能超过8192个字符")
    //   return
    // }
    setErrorMsg('')
    setResultContent('好嘞，请允许我思考一下...')

    const params = {
      "content": selected_content,
      "processing": processing,
      "tone": tone,
      "others": others
    }
    const authorization = `Authorization: Bearer ${mdmUserInfo.token}`
    const headers = {
      'token': mdmUserInfo.token,
      'Content-Type': 'application/json; charset=utf-8;',
      "Accept":"text/event-stream;charset=utf-8;"
    }
    const data = {
      "user": userInfo?.nickName || "",
      "convId": convIdHere, // 会话id,如果为NULL则创建新的会话
      "appId": XZ_APP_ID, // 智能体id
      "query": '开始', // 对话问题
      "inputs":{    // 会话参数 key 为参数名，value为参数值
        ...params
      }
    }
    sendStreamRequest(`${BASE_URL}${CHAT_PATH}`,"POST",data, headers,(success: boolean, word:String, conversation_id:string)=>{
      console.log("success",success)
      if(success){
        setResultContent(word as string)
        setConvId(conversation_id)
      }else {
        setErrorMsg(word as string)
        setResultContent('')
      }
    })
  }

  const reset = (e: React.MouseEvent<HTMLButtonElement>) => {
    e.preventDefault()
    setErrorMsg('')
    setResultContent('')
    setProcessing('')
    setTone('')
    setOthers('')
    setConvId('')
  }

  const getIcon = (name="",suffix='png') => {
    console.log(require(`./images/${name}.${suffix}`))
    return require(`./images/${name}.${suffix}`);
  }
  return (
    <>
      {/* <div className="wordcount-demo">
        <h2>
          当前文档字数为：<span className="count">{count} </span>个
        </h2>
      </div> */}
      <div className="document-ai-container">
        <div className='option-area'>
          <form id="operate-form">
          <div className='document-ai-operate'>
            <div className='option-title'>
              <h3>操作</h3>
            </div>
            <div className='option-value'>
              <input type="radio" id="summarize" name="processing" value="总结" checked={processing === '总结'} onClick={handleProcessingClick} onChange={handleProcessingChange}/>
              <label htmlFor="summarize" className='option summarize'>
                <div className="dot"></div>
                <span>总结</span>
              </label>

              <input type="radio" id="embellish" name="processing" value="润色" checked={processing === '润色'} onClick={handleProcessingClick} onChange={handleProcessingChange}/>
              <label htmlFor="embellish" className='option embellish'>
                <div className="dot"></div>
                <span>润色</span>
              </label>

              <input type="radio" id="correct" name="processing" value="修正" checked={processing ===  '修正'} onClick={handleProcessingClick} onChange={handleProcessingChange}/>
              <label htmlFor="correct" className='option correct'>
                <div className="dot"></div>
                <span>修正</span>
              </label>

              <input type="radio" id="continued" name="processing" value="续写" checked={processing === '续写'} onClick={handleProcessingClick} onChange={handleProcessingChange}/>
              <label htmlFor="continued" className='option continued'>
                <div className="dot"></div>
                <span>续写</span>
              </label>

              <input type="radio" id="expand" name="processing" value="扩写" checked={processing === '扩写'} onClick={handleProcessingClick} onChange={handleProcessingChange}/>
              <label htmlFor="expand" className='option expand'>
                <div className="dot"></div>
                <span>扩写</span>
              </label>

              {/* <input type="radio" id="generate_titles" name="processing" value="生成标题" checked={processing === '生成标题'} onClick={handleProcessingClick} onChange={handleProcessingChange}/>
              <label htmlFor="generate_titles" className='option generate_titles'>
                <div className="dot"></div>
                <span>生成标题</span>
              </label> */}

            </div>
          </div>
          <div className='document-ai-tone-area'>
            <div className='option-title'>
              <h3>调整语气</h3>
            </div>
            <div className='option-value'>
              <input type="radio" id="official" name="tone" value="正式的" checked={tone === '正式的'} onClick={handleToneClick}  onChange={handleToneChange}/>
              <label htmlFor="official" className='option official'>
                <div className="dot"></div>
                <span>正式的</span>
              </label>

              <input type="radio" id="unbend" name="tone" value="随意的" checked={tone === '随意的'} onClick={handleToneClick} onChange={handleToneChange}/>
              <label htmlFor="unbend" className='option unbend'>
                <div className="dot"></div>
                <span>随意的</span>
              </label>

              <input type="radio" id="professional" name="tone" value="专业的" checked={tone === '专业的'} onClick={handleToneClick} onChange={handleToneChange}/>
              <label htmlFor="professional" className='option professional'>
                <div className="dot"></div>
                <span>专业的</span>
              </label>

              <input type="radio" id="passionate" name="tone" value="热情的" checked={tone === '热情的'} onClick={handleToneClick} onChange={handleToneChange}/>
              <label htmlFor="passionate" className='option passionate'>
                <div className="dot"></div>
                <span>热情的</span>
              </label>

              <input type="radio" id="funny" name="tone" value="有趣的" checked={tone === '有趣的'} onClick={handleToneClick} onChange={handleToneChange}/>
              <label htmlFor="funny" className='option funny'>
                <div className="dot"></div>
                <span>有趣的</span>
              </label>

              <input type="radio" id="Informative" name="tone" value="有信息量的" checked={tone === '有信息量的'} onClick={handleToneClick} onChange={handleToneChange}/>
              <label htmlFor="Informative" className='option Informative'>
                <div className="dot"></div>
                <span>有信息量的</span>
              </label>
            </div>
          </div>
          <br />
          <textarea name="" id="others" className='input-other-requirements' placeholder='请描述您的其他要求' value={others} onChange={handleOthersChange}></textarea>
          <div className='confirm-area'>
            <button className={`btn-container ${!processing && !tone ? 'disable':''}`} onClick={() =>confirm(false)} type="button">确定</button>
            <button value="重置按钮" className='btn-container' type="button" onClick={reset}>重置</button>
          </div>
          </form>
        </div>
        {
          errorMsg && errorMsg.length > 0 &&
          <div className='error-area'>
            {errorMsg}
          </div>
        }
       
        <div className='document-ai-result-area scrollable-container' style={{height: resultAreaHeight}}>
          <Markdown>{resultContent}</Markdown>
        </div>
        <div className='document-ai-confirm-area'>
          <a href="#" onClick={()=> {confirm(true)}} className='confirm-block'><img src={getIcon('refresh')} alt="重新生成" />重新生成</a>
          <a href="#" onClick={appendBlockWithResultContent} className='append-block'><img src={getIcon('insert')} alt="插入结果" />插入结果</a>
          <a href="#" onClick={clean} className='append-block'><img src={getIcon('clean')} alt="清空" />清空</a>
        </div>
        
      </div>
    </>
  );
};